﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using WAPISF;

namespace UnitTests
{
    public class TestEntityClass
    {
        public int FID { get; set; }
        public string ST_FIPS { get; set; }
        public string SFIPS { get; set; }
        public string COUNTY_FIP { get; set; }
        public string CFIPS { get; set; }
        public string PL_FIPS { get; set; }
        public string ID { get; set; }
        public string ELEVATION { get; set; }
        public Nullable<long> POP_1990 { get; set; }
        public string POPULATION { get; set; }
        public string NAME { get; set; }
        public string ST { get; set; }
        public string STATE { get; set; }
        public string WARNGENLEV { get; set; }
        public string WARNGENTYP { get; set; }
        public string WATCH_WARN { get; set; }
        public Nullable<long> ZWATCH_WAR { get; set; }
        public Nullable<long> PROG_DISC { get; set; }
        public Nullable<long> ZPROG_DISC { get; set; }
        public Nullable<long> COMBOFLAG { get; set; }
        public string LAND_WATER { get; set; }
        public Nullable<long> RECNUM { get; set; }
        public Nullable<double> LON { get; set; }
        public Nullable<double> LAT { get; set; }
        public System.Data.Spatial.DbGeometry geom { get; set; }
    }

    [TestClass]
    public class GeoJsonFormatterTests
    {
        [TestMethod]
        public void TestPoint()
        {
            List<TestEntityClass> cities = new List<TestEntityClass>();

            TestEntityClass city = new TestEntityClass
            {
                FID = 1,
                ST_FIPS = "13",
                SFIPS = "13",
                COUNTY_FIP = "179",
                CFIPS = "179",
                PL_FIPS = "80256",
                ID = "348148",
                ELEVATION = "71",
                POP_1990 = 2024,
                POPULATION = "4030",
                NAME = "AIMAR",
                ST = "GA",
                STATE = "GEORGIA",
                WARNGENLEV = "3",
                WARNGENTYP = "",
                WATCH_WARN = "3",
                ZWATCH_WAR = 0,
                PROG_DISC = 230,
                ZPROG_DISC = 3640,
                COMBOFLAG = 0,
                LAND_WATER = "",
                RECNUM = 0,
                LON = -81.6717,
                LAT = 31.7528,
                geom = System.Data.Spatial.DbGeometry.FromText("POINT (-81.6717 31.7528)", 1)
            };
            cities.Add(city);
            GeoJsonFormatter formatter = new GeoJsonFormatter();
            bool can = formatter.CanWriteType(cities.GetType());
            MemoryStream memoryStream = new MemoryStream();
            HttpContent content = new StringContent(String.Empty);
            TransportContext transportContext = null;
            Task task = formatter.WriteToStreamAsync(cities.GetType(), cities, memoryStream, content, transportContext);
            task.Wait();
            memoryStream.Position = 0;
            string serializedString = new StreamReader(memoryStream).ReadToEnd();

            string expected = "{\"type\":\"FeatureCollection\",\"crs\":{\"type\":\"name\",\"properties\":{\"name\":\"EPSG:1\"}},\"features\":[{\"type\":\"Feature\",\"geometry\":{\"type\":\"Point\",\"coordinates\":[-81.6717,31.7528]},\"properties\":{\"FID\":1,\"ST_FIPS\":\"13\",\"SFIPS\":\"13\",\"COUNTY_FIP\":\"179\",\"CFIPS\":\"179\",\"PL_FIPS\":\"80256\",\"ID\":\"348148\",\"ELEVATION\":\"71\",\"POPULATION\":\"4030\",\"NAME\":\"AIMAR\",\"ST\":\"GA\",\"STATE\":\"GEORGIA\",\"WARNGENLEV\":\"3\",\"WARNGENTYP\":\"\",\"WATCH_WARN\":\"3\",\"LAND_WATER\":\"\"}}]}";
            Assert.AreEqual(expected, serializedString);
        }


        [TestMethod]
        public void TestLine()
        {
            List<TestEntityClass> cities = new List<TestEntityClass>();

            TestEntityClass city = new TestEntityClass
            {
                FID = 1,
                geom = System.Data.Spatial.DbGeometry.FromText("LINESTRING (30 10, 10 30, 40 40)", 1)
            };
            cities.Add(city);

            GeoJsonFormatter formatter = new GeoJsonFormatter();
            MemoryStream memoryStream = new MemoryStream();
            HttpContent content = new StringContent(String.Empty);
            TransportContext transportContext = null;
            Task task = formatter.WriteToStreamAsync(cities.GetType(), cities, memoryStream, content, transportContext);
            task.Wait();
            memoryStream.Position = 0;
            string serializedString = new StreamReader(memoryStream).ReadToEnd();

        }

        [TestMethod]
        public void TestPolygon()
        {
            List<TestEntityClass> cities = new List<TestEntityClass>();

            TestEntityClass city = new TestEntityClass
            {
                FID = 1,
                ST_FIPS = "13",
                SFIPS = "13",
                COUNTY_FIP = "179",
                CFIPS = "179",
                PL_FIPS = "80256",
                ID = "348148",
                ELEVATION = "71",
                POP_1990 = 2024,
                POPULATION = "4030",
                NAME = "AIMAR",
                ST = "GA",
                STATE = "GEORGIA",
                WARNGENLEV = "3",
                WARNGENTYP = "",
                WATCH_WARN = "3",
                ZWATCH_WAR = 0,
                PROG_DISC = 230,
                ZPROG_DISC = 3640,
                COMBOFLAG = 0,
                LAND_WATER = "",
                RECNUM = 0,
                LON = -81.6717,
                LAT = 31.7528,
                geom = System.Data.Spatial.DbGeometry.FromText("POLYGON ((35 10, 10 20, 15 40, 45 45, 35 10))", 1)
            };
            cities.Add(city);
            GeoJsonFormatter formatter = new GeoJsonFormatter();
            bool can = formatter.CanWriteType(cities.GetType());
            MemoryStream memoryStream = new MemoryStream();
            HttpContent content = new StringContent(String.Empty);
            TransportContext transportContext = null;
            Task task = formatter.WriteToStreamAsync(cities.GetType(), cities, memoryStream, content, transportContext);
            task.Wait();
            memoryStream.Position = 0;
            string serializedString = new StreamReader(memoryStream).ReadToEnd();

            string expected = "{\"type\":\"FeatureCollection\",\"crs\":{\"type\":\"name\",\"properties\":{\"name\":\"EPSG:1\"}},\"features\":[{\"type\":\"Feature\",\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[35.0,10.0],[10.0,20.0],[15.0,40.0],[45.0,45.0],[35.0,10.0]]]},\"properties\":{\"FID\":1,\"ST_FIPS\":\"13\",\"SFIPS\":\"13\",\"COUNTY_FIP\":\"179\",\"CFIPS\":\"179\",\"PL_FIPS\":\"80256\",\"ID\":\"348148\",\"ELEVATION\":\"71\",\"POPULATION\":\"4030\",\"NAME\":\"AIMAR\",\"ST\":\"GA\",\"STATE\":\"GEORGIA\",\"WARNGENLEV\":\"3\",\"WARNGENTYP\":\"\",\"WATCH_WARN\":\"3\",\"LAND_WATER\":\"\"}}]}";
            Assert.AreEqual(expected, serializedString);
        }

        [TestMethod]
        public void TestPolygonWithInterior()
        {
            List<TestEntityClass> cities = new List<TestEntityClass>();

            TestEntityClass city = new TestEntityClass
            {
                FID = 1,
                ST_FIPS = "13",
                SFIPS = "13",
                COUNTY_FIP = "179",
                CFIPS = "179",
                PL_FIPS = "80256",
                ID = "348148",
                ELEVATION = "71",
                POP_1990 = 2024,
                POPULATION = "4030",
                NAME = "AIMAR",
                ST = "GA",
                STATE = "GEORGIA",
                WARNGENLEV = "3",
                WARNGENTYP = "",
                WATCH_WARN = "3",
                ZWATCH_WAR = 0,
                PROG_DISC = 230,
                ZPROG_DISC = 3640,
                COMBOFLAG = 0,
                LAND_WATER = "",
                RECNUM = 0,
                LON = -81.6717,
                LAT = 31.7528,
                geom = System.Data.Spatial.DbGeometry.FromText("POLYGON ((35 10, 10 20, 15 40, 45 45, 35 10),(20 30, 35 35, 30 20, 20 30))", 1)
            };
            cities.Add(city);
            //cities.Add(city);
            GeoJsonFormatter formatter = new GeoJsonFormatter();
            bool can = formatter.CanWriteType(cities.GetType());
            MemoryStream memoryStream = new MemoryStream();
            HttpContent content = new StringContent(String.Empty);
            TransportContext transportContext = null;
            Task task = formatter.WriteToStreamAsync(cities.GetType(), cities, memoryStream, content, transportContext);
            task.Wait();
            memoryStream.Position = 0;
            string serializedString = new StreamReader(memoryStream).ReadToEnd();

            string expected = "{\"type\":\"FeatureCollection\",\"crs\":{\"type\":\"name\",\"properties\":{\"name\":\"EPSG:1\"}},\"features\":[{\"type\":\"Feature\",\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[35.0,10.0],[10.0,20.0],[15.0,40.0],[45.0,45.0],[35.0,10.0]],[[20.0,30.0],[35.0,35.0],[30.0,20.0],[20.0,30.0]]]},\"properties\":{\"FID\":1,\"ST_FIPS\":\"13\",\"SFIPS\":\"13\",\"COUNTY_FIP\":\"179\",\"CFIPS\":\"179\",\"PL_FIPS\":\"80256\",\"ID\":\"348148\",\"ELEVATION\":\"71\",\"POPULATION\":\"4030\",\"NAME\":\"AIMAR\",\"ST\":\"GA\",\"STATE\":\"GEORGIA\",\"WARNGENLEV\":\"3\",\"WARNGENTYP\":\"\",\"WATCH_WARN\":\"3\",\"LAND_WATER\":\"\"}}]}";
            Assert.AreEqual(expected, serializedString);
        }

        [TestMethod]
        public void TestGeoJsonToClass()
        {
            GeoJsonFormatter formatter = new GeoJsonFormatter();
            HttpContent content = new StringContent(String.Empty);
            TransportContext transportContext = null;

            string json = "{\"type\":\"FeatureCollection\",\"crs\":{\"type\":\"name\",\"properties\":{\"name\":\"EPSG:1\"}},\"features\":[{\"type\":\"Feature\",\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[35.0,10.0],[10.0,20.0],[15.0,40.0],[45.0,45.0],[35.0,10.0]],[[20.0,30.0],[35.0,35.0],[30.0,20.0],[20.0,30.0]]]},\"properties\":{\"FID\":1,\"ST_FIPS\":\"13\",\"SFIPS\":\"13\",\"COUNTY_FIP\":\"179\",\"CFIPS\":\"179\",\"PL_FIPS\":\"80256\",\"ID\":\"348148\",\"ELEVATION\":\"71\",\"POPULATION\":\"4030\",\"NAME\":\"AIMAR\",\"ST\":\"GA\",\"STATE\":\"GEORGIA\",\"WARNGENLEV\":\"3\",\"WARNGENTYP\":\"\",\"WATCH_WARN\":\"3\",\"LAND_WATER\":\"\"}}]}";
            using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(json)))
            {
                Task<object> task = formatter.ReadFromStreamAsync(typeof(TestEntityClass), ms, content: null, formatterLogger: null);
                task.Wait();

                IList cities = (IList)task.Result;
                foreach (TestEntityClass item in cities)
                {
                    Assert.IsTrue(item.STATE == "GEORGIA");
                }
            }
        }
    }
}
